/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package slideskinbuilder;
/*
 * Viewer.java
 *
 * Created on June 18, 2008, 10:23 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */


/**
 *
 * @author ew562c
 */
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.lang.*;

import java.io.File;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
        
import java.awt.geom.AffineTransform;
import java.awt.image.*;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;

import java.io.*;

public class Viewer extends JPanel {

        Image bgImg;
        Image fgImg;
        Image glowImg;

        Image coverArtImg;

        String bgName;
        String fgName;
        String glowName;
        
        int _x, _y, _maxZoom, _minZoom, _falloff;
        int _glowx, _glowy;
        
        int _coverCount;

        int _spacing = 0;

        int _selectedIndex;
        int _falloffType;
        
        final int LINEAR_FALLOFF = 0;

        final int ALIGN_CENTER = 0;
        final int ALIGN_TOP = 1;
        final int ALIGN_BOTTOM = 2;

        int _align = ALIGN_TOP;

        MediaTracker tracker;
        Color bgColor;

        public Viewer() {
            bgColor = Color.WHITE;
            tracker = new MediaTracker(this);

            _x = 200;
            _y = 200;

            _maxZoom = 100;
            _minZoom = 50;
            _falloff = 10;
            _falloffType = LINEAR_FALLOFF;
            
            _coverCount = 10;

            _selectedIndex = 50;

            //Load default cover at
           Toolkit toolkit = Toolkit.getDefaultToolkit();
           coverArtImg = toolkit.getImage("Cover.png");


            tracker.addImage(coverArtImg, 0);

            // Start downloading the image and wait until it finishes loading.
            try {
                tracker.waitForAll();
            }
            catch(InterruptedException e) {}
        }

        public void Save(File saveFile)
        {

                 System.out.println("You chose to save this file: " +
                 saveFile.getAbsolutePath());

                 try{
                     FileOutputStream out;
                     out = new FileOutputStream(saveFile.getAbsolutePath());
                     PrintStream p = new PrintStream(out);
                     p.println("<?xml version=\"1.0\"?>");
                     p.println("<skin");
                     p.println("   title='Unknown'");
                     p.println("   description='Unknown'");
                     p.println("   author='Unknown'");
                     p.println(">");

                    p.println("   <images");
                    p.println("      bg_img='"+bgName+"'");
                    p.println("      fg_img='"+fgName+"'");
                    p.println("      glow_img='"+glowName+"'");
                    p.println("      glow_x='"+this._glowx+"'");
                    p.println("      glow_y='"+this._glowy+"'");
                    p.println("      cover_x='"+this._x+"'");
                    p.println("      cover_y='"+this._y+"'");
                    p.println("      align='"+this._align+"'");
                    p.println("   />");

                    p.println("   <color");
                    p.println("      r='"+bgColor.getRed()+"'");
                    p.println("      g='"+bgColor.getGreen()+"'");
                    p.println("      b='"+bgColor.getBlue()+"'");
                    p.println("   />");

                    p.println("   <Falloff");
                    p.println("      func='"+0+"'");
                    p.println("      max_zoom='"+this._maxZoom+"'");
                    p.println("      min_zoom='"+this._minZoom+"'");
                    p.println("      falloff='"+this._falloff+"'");
                    p.println("      spacing='"+this._spacing+"'");
                    p.println("   />");

                     p.println("</skin>");
                     p.close();
                 } catch (Exception e)
                 {
                     System.err.println("Error writing to file.");
                 }

               /* try{
                     XMLConfiguration out_file = new XMLConfiguration(saveFile.getAbsolutePath());
                    // out_file.setRootElementName("levels");

                } catch (ConfigurationException configEx) {
                  //  configEx.printStackTrace();
                }
                 */

        }

        public void Load(File loadFile)
        {
            int x, y;
            double rot, zoom;
            Object prop;
            String fname;
            XMLConfiguration config;

          /*  try{
                config = new XMLConfiguration(); //loadFile.getAbsolutePath());
                try{
                    config.load(loadFile);
                    config.getString("[@title]");
                    config.getString("[@description]");
                    config.getString("[@author]");

                    bgName = config.getString("images[@bg_img]");
                    fgName = config.getString("images[@fg_img]");
                    glowName = config.getString("images[@glow_img]");

                    _x = config.getInt("images[@cover_x]");
                    _y = config.getInt("images[@cover_y]");
                    _glowx = config.getInt("images[@glow_x]");
                    _glowy = config.getInt("images[@glow_y]");
                    _align = config.getInt("images[@align]");

                    _maxZoom = config.getInt("Falloff[@max_zoom]");
                    _minZoom = config.getInt("Falloff[@min_zoom]");
                    _falloff = config.getInt("Falloff[@falloff]");
                    _spacing = config.getInt("Falloff[@spacing]");

                    int r = config.getInt("color[@r]");
                    int g = config.getInt("color[@g]");
                    int b = config.getInt("color[@b]");

                    bgColor = new Color(r, g, b);
             } catch (ConfigurationException configEx) {
            //    configEx.printStackTrace();
            }
            //finally{}
*/
        }
        
        public void SetBackgroundColor(Color c)
        {
           // bone_image_name = i;
           bgColor = c;

            paint(this.getGraphics());
        }

        public void SetBackgroundImage(File i)
        {
            bgName = i.getName();

           Toolkit toolkit = Toolkit.getDefaultToolkit();
           bgImg = toolkit.getImage(i.getAbsolutePath());


            tracker.addImage(bgImg, 0);

            // Start downloading the image and wait until it finishes loading.
            try {
                tracker.waitForAll();
            }
            catch(InterruptedException e) {}

           paint(this.getGraphics());
        }

        public void SetCoverCount(int c)
        {
            _coverCount = c;
            repaint();
        }

        public void SetX(int x)
        {
            _x = x;
            repaint();
        }

        public void SetGlowX(int x)
        {
            _glowx = x;
            repaint();
        }

        public void SetGlowY(int y)
        {
            _glowy = y;
            repaint();
        }
        
        public void SetMaxZoom(int z)
        {
            _maxZoom = z;
            repaint();
        }

        public void SetAlign(int a)
        {
            _align = a;
            repaint();
        }

        public void SetMinZoom(int z)
        {
            _minZoom = z;
            repaint();
        }

        public void SetFalloff(int f)
        {
            _falloff = f;
            repaint();
        }

        public void SetSpacing(int s)
        {
            _spacing = s;
            repaint();
        }

        public void SetY(int y)
        {
            _y = y;
            repaint();
        }

        public void SetSelectedIndex(int i)
        {
            _selectedIndex = i;
            repaint();
        }

        public void SetForegroundImage(File i)
        {

            fgName = i.getName();

           Toolkit toolkit = Toolkit.getDefaultToolkit();
           fgImg = toolkit.getImage(i.getAbsolutePath());

            tracker.addImage(fgImg, 0);

            // Start downloading the image and wait until it finishes loading.
            try {
                tracker.waitForAll();
            }
            catch(InterruptedException e) {}

            paint(this.getGraphics());
        }

        public void SetGlowImage(File i)
        {
            glowName = i.getName();

           Toolkit toolkit = Toolkit.getDefaultToolkit();
           glowImg = toolkit.getImage(i.getAbsolutePath());

            tracker.addImage(glowImg, 0);

            // Start downloading the image and wait until it finishes loading.
            try {
                tracker.waitForAll();
            }
            catch(InterruptedException e) {}

                paint(this.getGraphics());
            }

        public void UpdateImages()
        {
            paint(this.getGraphics());
        }

        public void ClearAll()
        {
                fgImg = null;
                glowImg = null;
                bgImg = null;
                
                repaint();
        }

        public int getIndex()
        {
            double si = _selectedIndex;
            double cc = _coverCount;
            si = cc*(si/100.0);

            if(si == _coverCount)
            {
                return (int)si - 1;
            }

            return (int)si;
        }

        public int calculateZoom(int index)
        {
            if(index == getIndex())
            {
                return _maxZoom;
            }

            if(Math.abs(index - getIndex()) > _falloff)
            {
                return _minZoom;
            }
            else
            {
                if(_falloffType == LINEAR_FALLOFF)
                {
                    int dist = Math.abs(index - getIndex());

                    int dz = _maxZoom - _minZoom;

                    return (_minZoom + ((dz/_falloff) * (_falloff - dist)));
                }
                else
                {
                    return 0;
                }
            }
        }

        private BufferedImage toBufferedImage(Image image) {
            if (image instanceof BufferedImage) {
                return (BufferedImage)image;
            }

            // This code ensures that all the pixels in the <strong class="highlight">image</strong> are loaded
            image = new ImageIcon(image).getImage();

            // Determine if the <strong class="highlight">image</strong> has transparent pixels; for this method's
            // implementation, see e661 Determining If an <strong class="highlight">Image</strong> Has Transparent Pixels
            boolean hasAlpha = hasAlpha(image);

            // Create a buffered <strong class="highlight">image</strong> with a format that's compatible with the screen
            BufferedImage bimage = null;
            GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
            try {
                // Determine the type of transparency of the new buffered <strong class="highlight">image</strong>
                int transparency = Transparency.OPAQUE;
                if (hasAlpha) {
                    transparency = Transparency.BITMASK;
                }

                // Create the buffered <strong class="highlight">image</strong>
                GraphicsDevice gs = ge.getDefaultScreenDevice();
                GraphicsConfiguration gc = gs.getDefaultConfiguration();
                bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency);
            } catch (HeadlessException e) {
                // The system does not have a screen
            }

            if (bimage == null) {
                int type = BufferedImage.TYPE_INT_RGB;
                if (hasAlpha) {
                    type = BufferedImage.TYPE_INT_ARGB;
                }
                bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
            }

              Graphics g = bimage.createGraphics();

            g.drawImage(image, 0, 0, image.getWidth(null), image.getHeight(null), null);
            g.dispose();

            return bimage;
        }
    
        public static boolean hasAlpha(Image image) {
            // If buffered <strong class="highlight">image</strong>, the color model is readily available
            if (image instanceof BufferedImage) {
                BufferedImage bimage = (BufferedImage)image;
                return bimage.getColorModel().hasAlpha();
            }

            // grabbing a single pixel is usually sufficient
             PixelGrabber pg = new PixelGrabber(image, 0, 0, 1, 1, false);
            try {
                pg.grabPixels();
            } catch (InterruptedException e) {
            }

            // Get the image's color model
            ColorModel cm = pg.getColorModel();
            return cm.hasAlpha();
        }
        
        public int calculateX(int index)
        {
            float z;

            int tx = _x;

            if(index < getIndex())
            {
                for(int i = index; i < getIndex(); i++) // i > index; i--)
                {
                    double dz = ((double)calculateZoom(i)/100.0);
                    tx = (int)((double)tx - (dz)*(double)this.coverArtImg.getWidth(this));
                }

                tx -= _spacing*(getIndex() - index);
            }
            else if(index > getIndex())
            {
                for(int i = index-1; i >= getIndex(); i--)
                {
                    double dz = ((double)calculateZoom(i)/100.0);
                    tx = (int)((double)tx + (dz)*(double)this.coverArtImg.getWidth(this));
                }

                tx += _spacing*(index - getIndex());
            }
            
            return tx;
        }

        public int calculateY(int index)
        {
            if(_align == ALIGN_TOP)
            {
                return _y;
            }
            else if(_align == ALIGN_BOTTOM)
            {
                return _y + (int)((((double)_maxZoom/100.0)*(double)this.coverArtImg.getHeight(this)) - GetZoomCoverImage((double)calculateZoom(index)/100.0).getHeight(this));
            }
            else
            {
                return _y + (int)((((double)_maxZoom/100.0)*(double)this.coverArtImg.getHeight(this))/2.0 - (double)(GetZoomCoverImage((double)calculateZoom(index)/100.0).getHeight(this))/2.0);
            }
        }

        Image GetZoomCoverImage(double zoom)
        {
            BufferedImage bi = new BufferedImage(this.coverArtImg.getWidth(this), coverArtImg.getHeight(this), BufferedImage.TYPE_INT_ARGB);

            Graphics2D g = (Graphics2D)bi.getGraphics();
            g.drawImage(coverArtImg,0, 0,null);
           // g.setClip(0,0,640,480);
            AffineTransform at = new AffineTransform();
            at.scale(zoom, zoom);

            BufferedImageOp bio;

          //  AffineTransform translationTransform;
          //  translationTransform = findTranslation(at, bi);
          //  at.preConcatenate(translationTransform);

            bio = new AffineTransformOp(at,AffineTransformOp.TYPE_BILINEAR);
            BufferedImage dbio = bio.filter(bi, null);

            return dbio;

        }

        public void ScreenShot(File saveFile)
        {
            try{

                Image img = this.createImage(getWidth(), getHeight());
                Graphics g = img.getGraphics();

                paint(g);

                ImageIO.write(toBufferedImage(img), "gif", saveFile);

                JOptionPane.showMessageDialog(null, "Image saved.");
                g.dispose();
            }catch(Exception ex){
                //ex.printStackTrace();
            }
        }

        public void paint(Graphics graphics) {
                //Draw Walls
                graphics.setColor(bgColor);
                graphics.clearRect(0, 0, 640, 480);
                graphics.fillRect(0,0,640,480);

                if(bgImg != null)
                {
                   graphics.drawImage(bgImg, 0, 0, null);
                }

                int storeSelected = -1;

                if(coverArtImg != null)
                {
                   if(this._coverCount > 0)
                   {
                       double si = _selectedIndex;
                       double p = (si / 100.0);

                       System.out.print("P:");
                       System.out.println(p);
                       
                       int selected = (int)(p*_coverCount);

                       for(int i = 0; i < selected; i++)
                       {
                           int tx, ty;
                           int z;

                           z = calculateZoom(i);
                           tx = calculateX(i);
                           ty = calculateY(i);

                           graphics.drawImage(GetZoomCoverImage((double)z/100.0), tx, ty, null);
                       }

                       for(int i = _coverCount-1; i > selected; i--)
                       {
                           int tx, ty;
                           int z;

                           z = calculateZoom(i);
                           tx = calculateX(i);
                           ty = calculateY(i);

                           graphics.drawImage(GetZoomCoverImage((double)z/100.0), tx, ty, null);
                       }

                       if(_coverCount > 0)
                       {
                            double w = (double)coverArtImg.getWidth(this)*(double)_maxZoom/100.0;
                            double h = (double)coverArtImg.getHeight(this)*(double)_maxZoom/100.0;

                            System.out.print(w);
                            System.out.print("'");
                            System.out.print(h);

                            if(glowImg != null)
                            {
                               graphics.drawImage(glowImg, _glowx, _glowy, null);
                            }
                            
                            graphics.drawImage(GetZoomCoverImage((double)_maxZoom/100.0), _x, _y, null);
                       }
                   }

                }

                if(fgImg != null)
                {
                   graphics.drawImage(fgImg, 0, 0, null);
                }
        }
}

